package codegen;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Java代码生成器
 * 使用FreeMarker模板引擎生成Java类文件
 */
public class CodeGenerator {
    // FreeMarker配置对象
    private final Configuration freemarkerConfig;

    // 支持的数据类型列表
    private static final List<String> SUPPORTED_TYPES = Arrays.asList(
        "String", "Integer", "Long", "Double", "Float", "Boolean",
        "Date", "BigDecimal", "LocalDateTime", "LocalDate"
    );

    /**
     * 构造函数：初始化FreeMarker配置
     */
    public CodeGenerator() {
        freemarkerConfig = new Configuration(Configuration.VERSION_2_3_32);
        // 默认使用java目录下的模板
        freemarkerConfig.setClassLoaderForTemplateLoading(
            getClass().getClassLoader(), "templates/java");
        freemarkerConfig.setDefaultEncoding("UTF-8");
    }

    /**
     * 获取JSON相关的模板
     */
    private Template getJsonTemplate(String templateName) throws IOException {
        Configuration jsonConfig = new Configuration(Configuration.VERSION_2_3_32);
        jsonConfig.setClassLoaderForTemplateLoading(
            getClass().getClassLoader(), "templates/json");
        jsonConfig.setDefaultEncoding("UTF-8");
        return jsonConfig.getTemplate(templateName);
    }

    /**
     * 根据类型生成代码
     */
    public void generate(int type) throws IOException, TemplateException {
        Scanner scanner = new Scanner(System.in);

        switch (type) {
            case 1: // 实体类
                System.out.print("请输入包名 (例如 com.example.model): ");
                String packageName = scanner.nextLine();
                System.out.print("请输入类名: ");
                String className = scanner.nextLine();
                List<FieldDefinition> fields = new ArrayList<>();
                generateEntityFields(scanner, fields);
                generateJavaClass(packageName, className, fields, "src/main/java");
                break;

            case 2: // 比较器类
                System.out.print("请输入包名 (例如 com.example.model): ");
                packageName = scanner.nextLine();
                System.out.print("请输入类名: ");
                className = scanner.nextLine();
                fields = new ArrayList<>();
                generateComparatorFields(scanner, fields);
                generateJavaClass(packageName, className, fields, "src/main/java");
                generateComparator(packageName, className, fields, "src/main/java");
                generateCompareDemo(packageName, className, fields, "src/main/java");
                System.out.println("\n已生成演示程序: " + className + "Demo.java");
                break;

            case 3: // JSON转换器
                System.out.print("请输入包名 (例如 com.example.model): ");
                packageName = scanner.nextLine();
                System.out.print("请输入类名: ");
                className = scanner.nextLine();
                System.out.println("\n请输入JSON数据 (以空行结束):");
                generateFromJson(packageName, className, scanner);
                break;

            case 4: // JSON示例
                showJsonExamples();
                break;
        }
    }

    private void generateEntityFields(Scanner scanner, List<FieldDefinition> fields) {
        boolean continueAdding = true;
        while (continueAdding) {
            // 显示字段类型选项
            System.out.println("\n可用的数据类型：");
            for (int i = 0; i < SUPPORTED_TYPES.size(); i++) {
                System.out.printf("%d. %s%n", i + 1, SUPPORTED_TYPES.get(i));
            }

            System.out.print("请选择字段类型 (输入数字): ");
            int typeChoice = scanner.nextInt();
            scanner.nextLine(); // 消费换行符

            if (typeChoice >= 1 && typeChoice <= SUPPORTED_TYPES.size()) {
                String fieldType = SUPPORTED_TYPES.get(typeChoice - 1);

                System.out.print("请输入字段名: ");
                String fieldName = scanner.nextLine();

                fields.add(new FieldDefinition(fieldName, fieldType));

                System.out.print("\n是否继续添加字段？(y/n): ");
                continueAdding = scanner.nextLine().trim().equalsIgnoreCase("y");
            } else {
                System.out.println("无效的选择，请重试");
            }
        }
    }

    private void generateComparatorFields(Scanner scanner, List<FieldDefinition> fields) {
        System.out.println("\n请至少输入2个int类型的可比较字段");

        // 至少输入2个字段
        while (fields.size() < 2) {
            System.out.printf("请输入第%d个字段名称: ", fields.size() + 1);
            String fieldName = scanner.nextLine().trim();
            fields.add(new FieldDefinition(fieldName, "int"));
        }

        // 询问是否继续添加字段
        while (true) {
            System.out.print("\n是否继续添加字段？(y/n): ");
            if (!scanner.nextLine().trim().equalsIgnoreCase("y")) {
                break;
            }

            System.out.printf("请输入第%d个字段名称: ", fields.size() + 1);
            String fieldName = scanner.nextLine().trim();
            fields.add(new FieldDefinition(fieldName, "int"));
        }
    }

    /**
     * 生成Java类文件
     * @param packageName 包名
     * @param className 类名
     * @param fields 字段列表
     * @param outputPath 输出路径
     * @throws IOException 文件操作异常
     * @throws TemplateException 模板处理异常
     */
    public void generateJavaClass(String packageName, String className,
            List<FieldDefinition> fields, String outputPath) throws IOException, TemplateException {
        // 准备数据模型，用于填充模板
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("packageName", packageName);
        dataModel.put("className", className);
        dataModel.put("fields", fields);
        dataModel.put("imports", getRequiredImports(fields));  // 添加导入语句

        // 获取模板文件
        Template template = freemarkerConfig.getTemplate("java_class.ftl");

        // 确保输出目录存在
        Path dir = Paths.get(outputPath, packageName.replace(".", "/"));
        Files.createDirectories(dir);

        // 生成Java文件
        String filePath = dir.resolve(className + ".java").toString();
        try (Writer writer = new FileWriter(filePath)) {
            template.process(dataModel, writer);
        }
    }

    /**
     * 生成比较器类文件
     */
    public void generateComparator(String packageName, String className,
            List<FieldDefinition> fields, String outputPath) throws IOException, TemplateException {
        // 准备数据模型
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("packageName", packageName);
        dataModel.put("className", className);
        dataModel.put("fields", fields);

        // 获取模板文件
        Template template = freemarkerConfig.getTemplate("comparator_class.ftl");

        // 确保输出目录存在
        Path dir = Paths.get(outputPath, packageName.replace(".", "/"));
        Files.createDirectories(dir);

        // 生成比较器文件
        String filePath = dir.resolve(className + "Comparator.java").toString();
        try (Writer writer = new FileWriter(filePath)) {
            template.process(dataModel, writer);
        }
    }

    /**
     * 生成比较演示程序
     */
    public void generateCompareDemo(String packageName, String className,
            List<FieldDefinition> fields, String outputPath) throws IOException, TemplateException {
        // 准备数据模型
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("packageName", packageName);
        dataModel.put("className", className);
        dataModel.put("fields", fields);

        // 获取模板文件
        Template template = freemarkerConfig.getTemplate("compare_demo.ftl");

        // 确保输出目录存在
        Path dir = Paths.get(outputPath, packageName.replace(".", "/"));
        Files.createDirectories(dir);

        // 生成演示程序文件
        String filePath = dir.resolve(className + "Demo.java").toString();
        try (Writer writer = new FileWriter(filePath)) {
            template.process(dataModel, writer);
        }
    }

    /**
     * 生成JSON转换器
     */
    public void generateJsonConverter(String packageName, String className,
            List<FieldDefinition> fields, String outputPath) throws IOException, TemplateException {
        // 准备数据模型
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("packageName", packageName);
        dataModel.put("className", className);
        dataModel.put("fields", fields);

        // 获取模板文件
        Template template = freemarkerConfig.getTemplate("json_converter.ftl");

        // 确保输出目录存在
        Path dir = Paths.get(outputPath, packageName.replace(".", "/"));
        Files.createDirectories(dir);

        // 生成JSON转换器文件
        String filePath = dir.resolve(className + "JsonConverter.java").toString();
        try (Writer writer = new FileWriter(filePath)) {
            template.process(dataModel, writer);
        }
    }

    /**
     * 字段定义内部类
     * 用于描述Java类的字段信息
     */
    public static class FieldDefinition {
        private String name;    // 字段名
        private String type;    // 字段类型

        /**
         * 构造函数
         * @param name 字段名
         * @param type 字段类型
         */
        public FieldDefinition(String name, String type) {
            this.name = name;
            this.type = type;
        }

        // Getter方法
        public String getName() { return name; }
        public String getType() { return type; }

        // 添加首字母大写的getter方法，用于生成方法名
        public String getCapitalizedName() {
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
    }

    /**
     * 从JSON生成Java类
     */
    public void generateFromJson(String packageName, String className, Scanner scanner) throws IOException, TemplateException {
        StringBuilder jsonBuilder = new StringBuilder();
        String line;
        while (!(line = scanner.nextLine()).trim().isEmpty()) {
            jsonBuilder.append(line).append("\n");
        }
        String jsonString = jsonBuilder.toString().trim();

        // 解析JSON，提取字段信息
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(jsonString);

        // 存储所有需要生成的类信息
        Map<String, List<FieldDefinition>> allClasses = new HashMap<>();
        List<FieldDefinition> mainClassFields = new ArrayList<>();

        // 遍历JSON字段
        Iterator<Map.Entry<String, JsonNode>> fieldIterator = rootNode.fields();
        while (fieldIterator.hasNext()) {
            Map.Entry<String, JsonNode> entry = fieldIterator.next();
            String fieldName = entry.getKey();
            JsonNode value = entry.getValue();

            if (value.isObject()) {
                // 如果是对象，创建新的类
                String subClassName = capitalize(fieldName);
                mainClassFields.add(new FieldDefinition(fieldName, subClassName));
                processJsonObject(packageName, subClassName, value, allClasses);
            } else if (value.isArray() && value.size() > 0 && value.get(0).isObject()) {
                // 如果是对象数组，为数组元素创建新的类
                String subClassName = capitalize(fieldName.replaceAll("s$", ""));
                String fieldType = "List<" + subClassName + ">";
                mainClassFields.add(new FieldDefinition(fieldName, fieldType));
                processJsonObject(packageName, subClassName, value.get(0), allClasses);
            } else {
                String fieldType = getJavaType(value);
                mainClassFields.add(new FieldDefinition(fieldName, fieldType));
            }
        }

        // 存储主类信息
        allClasses.put(className, mainClassFields);

        // 生成所有类文件
        for (Map.Entry<String, List<FieldDefinition>> classInfo : allClasses.entrySet()) {
            String currentClassName = classInfo.getKey();
            List<FieldDefinition> fields = classInfo.getValue();

            // 准备数据模型
            Map<String, Object> dataModel = new HashMap<>();
            dataModel.put("packageName", packageName);
            dataModel.put("className", currentClassName);
            dataModel.put("fields", fields);
            dataModel.put("imports", getRequiredImports(fields));

            // 获取模板文件
            Template template = getJsonTemplate("json_entity.ftl");

            // 确保输出目录存在
            Path dir = Paths.get("src/main/java", packageName.replace(".", "/"));
            Files.createDirectories(dir);

            // 生成Java文件
            String filePath = dir.resolve(currentClassName + ".java").toString();
            try (Writer writer = new FileWriter(filePath)) {
                template.process(dataModel, writer);
            }

            System.out.println("已生成类文件: " + currentClassName + ".java");
        }
    }

    /**
     * 处理JSON对象，提取字段信息
     */
    private void processJsonObject(String packageName, String className, JsonNode jsonNode,
            Map<String, List<FieldDefinition>> allClasses) {
        List<FieldDefinition> fields = new ArrayList<>();

        Iterator<Map.Entry<String, JsonNode>> iterator = jsonNode.fields();
        while (iterator.hasNext()) {
            Map.Entry<String, JsonNode> entry = iterator.next();
            String fieldName = entry.getKey();
            JsonNode value = entry.getValue();

            if (value.isObject() && !isSimpleValueMap(value)) {
                String subClassName = capitalize(fieldName);
                fields.add(new FieldDefinition(fieldName, subClassName));
                processJsonObject(packageName, subClassName, value, allClasses);
            } else if (value.isArray() && value.size() > 0 && value.get(0).isObject()) {
                String subClassName = capitalize(fieldName.replaceAll("s$", ""));
                String fieldType = "List<" + subClassName + ">";
                fields.add(new FieldDefinition(fieldName, fieldType));
                processJsonObject(packageName, subClassName, value.get(0), allClasses);
            } else {
                String fieldType = getJavaType(value);
                fields.add(new FieldDefinition(fieldName, fieldType));
            }
        }

        allClasses.put(className, fields);
    }

    /**
     * 判断是否为简单值的Map
     */
    private boolean isSimpleValueMap(JsonNode node) {
        Iterator<JsonNode> elements = node.elements();
        while (elements.hasNext()) {
            if (!elements.next().isValueNode()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 首字母大写
     */
    private String capitalize(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 根据JSON值类型判断Java类型
     */
    private String getJavaType(JsonNode value) {
        if (value.isTextual()) {
            return "String";
        }
        if (value.isInt()) {
            return "Integer";
        }
        if (value.isLong()) {
            return "Long";
        }
        if (value.isDouble()) {
            return "Double";
        }
        if (value.isBoolean()) {
            return "Boolean";
        }
        if (value.isNull()) {
            return "Object";
        }
        if (value.isArray()) {
            // 处理数组类型
            if (value.size() > 0) {
                JsonNode firstElement = value.get(0);
                String elementType = getJavaType(firstElement);
                // 检查是否有重复元素
                Set<String> uniqueValues = new HashSet<>();
                for (JsonNode element : value) {
                    uniqueValues.add(element.toString());
                }
                boolean hasDuplicates = value.size() != uniqueValues.size();
                return hasDuplicates ? "List<" + elementType + ">" : "Set<" + elementType + ">";
            }
            return "List<Object>";
        }
        if (value.isObject()) {
            // 处理对象类型
            boolean isMap = true;
            Iterator<Map.Entry<String, JsonNode>> fields = value.fields();
            while (fields.hasNext()) {
                if (!fields.next().getValue().isValueNode()) {
                    isMap = false;
                    break;
                }
            }

            if (isMap && value.size() > 0) {
                // 如果所有字段都是简单值，则认为是Map
                String valueType = getJavaType(value.fields().next().getValue());
                return "Map<String, " + valueType + ">";
            }
            return "Object";
        }
        return "String";  // 默认类型
    }

    /**
     * 生成Java类时添加必要的导入语句
     */
    private Set<String> getRequiredImports(List<FieldDefinition> fields) {
        Set<String> imports = new HashSet<>();
        for (FieldDefinition field : fields) {
            String type = field.getType();
            if (type.startsWith("List")) {
                imports.add("java.util.List");
                imports.add("java.util.ArrayList");
            }
            if (type.startsWith("Set")) {
                imports.add("java.util.Set");
                imports.add("java.util.HashSet");
            }
            if (type.startsWith("Map")) {
                imports.add("java.util.Map");
                imports.add("java.util.HashMap");
            }
        }
        return imports;
    }

    /**
     * 显示随机JSON示例
     */
    public void showJsonExamples() throws IOException, TemplateException {
        Map<String, Object> dataModel = new HashMap<>();
        Random random = new Random();

        // 添加random对象到数据模型中
        dataModel.put("random", random);

        // 预生成随机数据
        dataModel.put("id", String.valueOf(random.nextInt(10000)));
        dataModel.put("age", String.valueOf(20 + random.nextInt(40)));
        dataModel.put("salary", String.format("%.2f", 8000 + random.nextInt(12000) + random.nextInt(100) / 100.0));
        dataModel.put("isActive", random.nextBoolean());

        // 生成分数列表
        List<String> scoreList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            scoreList.add(String.valueOf(80 + random.nextInt(20)));
        }
        dataModel.put("scores", scoreList);

        // 预定义的数据列表
        List<String> names = Arrays.asList("张三", "李四", "王五", "赵六", "钱七");
        List<String> emails = Arrays.asList("zhang", "li", "wang", "zhao", "qian");
        List<String> hobbies = Arrays.asList("读书", "游泳", "跑步", "篮球", "足球", "编程", "旅游", "摄影");
        List<String> techs = Arrays.asList("Java", "Python", "Go", "JavaScript", "C++", "Rust", "Kotlin", "Swift");
        List<String> cities = Arrays.asList("北京", "上海", "广州", "深圳", "杭州");
        List<String> districts = Arrays.asList("朝阳", "海淀", "浦东", "南山", "西湖");
        List<String> levels = Arrays.asList("VIP", "SVIP", "普通会员", "金牌会员", "钻石会员");
        List<String> ranks = Arrays.asList("青铜", "白银", "黄金", "铂金", "钻石");

        // 添加所有列表到数据模型中
        dataModel.put("names", names);
        dataModel.put("emails", emails);
        dataModel.put("hobbies", hobbies);
        dataModel.put("techs", techs);
        dataModel.put("cities", cities);
        dataModel.put("districts", districts);
        dataModel.put("levels", levels);
        dataModel.put("ranks", ranks);

        // 随机选择数据
        dataModel.put("name", names.get(random.nextInt(names.size())));
        dataModel.put("email", emails.get(random.nextInt(emails.size())) + random.nextInt(100) + "@example.com");
        dataModel.put("city", cities.get(random.nextInt(cities.size())));
        dataModel.put("district", districts.get(random.nextInt(districts.size())));
        dataModel.put("level", levels.get(random.nextInt(levels.size())));
        dataModel.put("rank", ranks.get(random.nextInt(ranks.size())));
        dataModel.put("phone", "138" + String.format("%08d", random.nextInt(100000000)));
        dataModel.put("orderId", "ORDER" + (100 + random.nextInt(900)));
        dataModel.put("amount", String.format("%.2f", random.nextInt(1000) + random.nextInt(100) / 100.0));
        dataModel.put("points", String.valueOf(random.nextInt(10000)));

        // 随机选择一个模板
        String[] templates = new String[] {
            "complex_order.ftl",
            "organization.ftl",
            "social_media.ftl",
            "ecommerce.ftl",
            "education.ftl",
            "game_system.ftl",
            "medical_system.ftl"
        };
        String templateName = templates[random.nextInt(templates.length)];
        System.out.println(templateName.replace(".ftl", ""));  // 显示使用的模板名称
        System.out.println();  // 空行分隔

        // 使用getJsonTemplate而不是freemarkerConfig
        Template exampleTemplate = getJsonTemplate(templateName);
        exampleTemplate.process(dataModel, new OutputStreamWriter(System.out));
    }

    /**
     * 创建实体类生成器
     */
    public void createEntityGenerator() throws IOException, TemplateException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n=== 实体类生成器制作 ===");

        // 获取生成器基本信息
        System.out.print("请输入生成器名称: ");
        String generatorName = scanner.nextLine();

        System.out.print("请输入生成器描述: ");
        String description = scanner.nextLine();

        // 创建模板
        System.out.println("\n请定义实体类模板：");
        System.out.println("1. 选择基础字段类型");
        System.out.println("2. 添加自定义注解");
        System.out.println("3. 配置getter/setter");
        System.out.println("4. 添加构造函数");

        // 保存生成器配置
        Map<String, Object> config = new HashMap<>();
        config.put("name", generatorName);
        config.put("description", description);
        config.put("type", "entity");

        // 生成模板文件
        saveGeneratorTemplate(generatorName, config);
        System.out.println("\n实体类生成器创建成功！");
    }

    /**
     * 创建模板生成器
     */
    public void createTemplateGenerator() throws IOException, TemplateException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n=== 模板生成器制作 ===");

        System.out.print("请输入模板名称: ");
        String templateName = scanner.nextLine();

        System.out.println("\n请输入模板内容 (输入EOF结束):");
        StringBuilder template = new StringBuilder();
        String line;
        while (!(line = scanner.nextLine()).equals("EOF")) {
            template.append(line).append("\n");
        }

        // 保存模板文件
        saveTemplate(templateName, template.toString());
        System.out.println("\n模板生成器创建成功！");
    }

    /**
     * 创建JSON示例生成器
     */
    public void createJsonExampleGenerator() throws IOException, TemplateException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n=== JSON示例生成器制作 ===");

        System.out.print("请输入JSON模板名称: ");
        String templateName = scanner.nextLine();

        System.out.println("\n请定义JSON结构：");
        System.out.println("1. 添加基础字段");
        System.out.println("2. 添加嵌套对象");
        System.out.println("3. 添加数组");
        System.out.println("4. 配置随机数据");

        // 保存JSON模板
        saveJsonTemplate(templateName);
        System.out.println("\nJSON示例生成器创建成功！");
    }

    /**
     * 创建自定义生成器
     */
    public void createCustomGenerator() throws IOException, TemplateException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n=== 自定义生成器制作 ===");

        System.out.print("请输入生成器名称: ");
        String generatorName = scanner.nextLine();

        System.out.println("\n请选择生成器类型：");
        System.out.println("1. 代码生成器");
        System.out.println("2. 文档生成器");
        System.out.println("3. 配置生成器");
        System.out.println("4. 其他类型");

        // 根据选择创建对应的生成器
        int choice = scanner.nextInt();
        scanner.nextLine();

        // 保存自定义生成器
        saveCustomGenerator(generatorName, choice);
        System.out.println("\n自定义生成器创建成功！");
    }

    /**
     * 保存生成器模板
     */
    private void saveGeneratorTemplate(String name, Map<String, Object> config) throws IOException {
        // 创建生成器目录
        Path dir = Paths.get("generators", name);
        Files.createDirectories(dir);

        // 保存配置文件
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(dir.resolve("config.json").toFile(), config);
    }

    /**
     * 保存模板文件
     */
    private void saveTemplate(String name, String content) throws IOException {
        Path dir = Paths.get("templates");
        Files.createDirectories(dir);
        Files.write(dir.resolve(name + ".ftl"), content.getBytes());
    }

    /**
     * 保存JSON模板
     */
    private void saveJsonTemplate(String name) throws IOException {
        Path dir = Paths.get("templates", "json");
        Files.createDirectories(dir);
        // 创建JSON模板文件
    }

    /**
     * 保存自定义生成器
     */
    private void saveCustomGenerator(String name, int type) throws IOException {
        Path dir = Paths.get("generators", "custom", name);
        Files.createDirectories(dir);
        // 创建自定义生成器文件
    }

    /**
     * 创建Spring Boot项目配置生成器
     */
    public void createConfigGenerator() throws Exception {
        Scanner scanner = new Scanner(System.in);
        Map<String, Object> config = new HashMap<>();

        // 设置依赖版本信息
        Map<String, String> versions = new HashMap<>();
        versions.put("java", "17");
        versions.put("mybatis", "2.2.2");
        versions.put("mysql", "8.0.29");
        versions.put("druid", "1.2.8");
        versions.put("jwt", "0.9.1");
        versions.put("fastjson", "1.2.83");
        versions.put("knife4j", "3.0.3");
        versions.put("mybatisPlus", "3.5.5");
        config.put("versions", versions);

        System.out.println("\n=== Spring Boot项目生成器 ===\n");

        // 收集基本信息
        System.out.println("--- 项目基本信息 ---");
        System.out.print("项目名称: ");
        String projectName = scanner.nextLine().trim();
        if (projectName.isEmpty()) {
            throw new IllegalArgumentException("项目名称不能为空");
        }
        config.put("name", projectName);

        System.out.print("项目描述(直接回车使用项目名): ");
        String description = scanner.nextLine().trim();
        if (description.isEmpty()) {
            description = projectName;
        }
        config.put("description", description);

        // 根据项目名生成包名和artifactId
        String basePackage = "com." + projectName.toLowerCase().replaceAll("[^a-zA-Z0-9]", "");
        String artifactId = projectName.toLowerCase().replaceAll("[^a-zA-Z0-9-]", "-");

        config.put("groupId", basePackage);
        config.put("basePackage", basePackage);
        config.put("artifactId", artifactId);

        System.out.print("版本号(直接回车使用1.0.0): ");
        String version = scanner.nextLine().trim();
        if (version.isEmpty()) {
            version = "1.0.0";
        }
        config.put("version", version);

        System.out.print("作者(直接回车使用系统用户名): ");
        String author = scanner.nextLine().trim();
        if (author.isEmpty()) {
            author = System.getProperty("user.name");
        }
        config.put("author", author);

        // 服务器配置
        System.out.println("\n--- 服务器配置 ---");
        System.out.print("服务器端口(直接回车使用8080): ");
        String serverPort = scanner.nextLine().trim();
        if (serverPort.isEmpty()) {
            serverPort = "8080";
        }
        config.put("serverPort", serverPort);

        // 询问是否需要数据库支持
        System.out.print("\n是否需要数据库支持? (y/n): ");
        boolean needDatabase = scanner.nextLine().trim().equalsIgnoreCase("y");
        config.put("needDatabase", needDatabase);

        if (needDatabase) {
            System.out.println("\n--- 数据库配置 ---");
            System.out.print("数据库主机(直接回车使用localhost): ");
            String databaseHost = scanner.nextLine().trim();
            if (databaseHost.isEmpty()) {
                databaseHost = "localhost";
            }
            config.put("databaseHost", databaseHost);

            System.out.print("数据库端口(直接回车使用3306): ");
            String databasePort = scanner.nextLine().trim();
            if (databasePort.isEmpty()) {
                databasePort = "3306";
            }
            config.put("databasePort", databasePort);

            System.out.print("数据库名称: ");
            String databaseName = scanner.nextLine().trim();
            if (databaseName.isEmpty()) {
                throw new IllegalArgumentException("数据库名称不能为空");
            }
            config.put("databaseName", databaseName);

            System.out.print("数据库用户名: ");
            String databaseUsername = scanner.nextLine().trim();
            if (databaseUsername.isEmpty()) {
                throw new IllegalArgumentException("数据库用户名不能为空");
            }
            config.put("databaseUsername", databaseUsername);

            System.out.print("数据库密码: ");
            String databasePassword = scanner.nextLine().trim();
            if (databasePassword.isEmpty()) {
                throw new IllegalArgumentException("数据库密码不能为空");
            }
            config.put("databasePassword", databasePassword);
        }

        // 询问是否需要Redis支持
        System.out.print("\n是否需要Redis支持? (y/n): ");
        boolean needRedis = scanner.nextLine().trim().equalsIgnoreCase("y");
        config.put("needRedis", needRedis);

        if (needRedis) {
            System.out.println("\n--- Redis配置 ---");
            System.out.print("Redis主机(直接回车使用localhost): ");
            String redisHost = scanner.nextLine().trim();
            if (redisHost.isEmpty()) {
                redisHost = "localhost";
            }
            config.put("redisHost", redisHost);

            System.out.print("Redis端口(直接回车使用6379): ");
            String redisPort = scanner.nextLine().trim();
            if (redisPort.isEmpty()) {
                redisPort = "6379";
            }
            config.put("redisPort", redisPort);

            System.out.print("Redis密码(可选,直接回车表示无密码): ");
            String redisPassword = scanner.nextLine().trim();
            if (!redisPassword.isEmpty()) {
                config.put("redisPassword", redisPassword);
            }
        }

        // 询问是否需要JWT支持
        System.out.print("\n是否需要JWT支持? (y/n): ");
        boolean needJwt = scanner.nextLine().trim().equalsIgnoreCase("y");
        config.put("needJwt", needJwt);
        if (needJwt) {
            config.put("jwtSecret", UUID.randomUUID().toString().replace("-", ""));
        }

        // 询问是否需要Swagger文档支持
        System.out.print("\n是否需要Swagger文档支持? (y/n): ");
        boolean needSwagger = scanner.nextLine().trim().equalsIgnoreCase("y");
        config.put("needSwagger", needSwagger);

        // 生成项目文件
        generateProjectFiles(config);

        System.out.println("\nSpring Boot项目生成完成!");
    }

    /**
     * 生成项目文件
     */
    private void generateProjectFiles(Map<String, Object> config) throws Exception {
        // 使用项目名作为基础目录
        String baseDir = config.get("name").toString().replaceAll("[^a-zA-Z0-9_-]", "_");
        String basePackage = config.get("basePackage").toString();

        // 创建项目目录结构
        createDirectoryStructure(baseDir, basePackage);

        // 1. 生成 pom.xml
        processTemplate("pom.xml.ftl", baseDir + "/pom.xml", config);

        // 2. 生成 application.yml
        processTemplate("application.yml.ftl", baseDir + "/src/main/resources/application.yml", config);

        // 3. 如果需要数据库支持,生成 mybatis-config.xml
        if (Boolean.TRUE.equals(config.get("needDatabase"))) {
            processTemplate("mybatis-config.xml.ftl", baseDir + "/src/main/resources/mybatis/mybatis-config.xml", config);
        }

        // 4. 生成主应用类
        String mainClassName = toPascalCase(config.get("name").toString()) + "Application";
        config.put("mainClassName", mainClassName);
        String mainClassPath = baseDir + "/src/main/java/" + basePackage.replace(".", "/") + "/" + mainClassName + ".java";
        processTemplate("Application.java.ftl", mainClassPath, config);

        // 5. 根据需要生成其他配置类和工具类
        if (Boolean.TRUE.equals(config.get("needSwagger"))) {
            String swaggerConfigPath = baseDir + "/src/main/java/" + basePackage.replace(".", "/") + "/config/SwaggerConfig.java";
            processTemplate("SwaggerConfig.java.ftl", swaggerConfigPath, config);
        }

        if (Boolean.TRUE.equals(config.get("needJwt"))) {
            String jwtUtilPath = baseDir + "/src/main/java/" + basePackage.replace(".", "/") + "/util/JwtUtil.java";
            processTemplate("JwtUtil.java.ftl", jwtUtilPath, config);
        }

        // 生成运行配置说明
        System.out.println("\n项目生成完成!");
        System.out.println("生成的文件包括:");
        System.out.println("1. pom.xml - Maven项目配置文件");
        System.out.println("2. application.yml - Spring Boot配置文件");
        if (Boolean.TRUE.equals(config.get("needDatabase"))) {
            System.out.println("3. mybatis-config.xml - MyBatis配置文件");
        }
        System.out.println("4. " + mainClassName + ".java - 主应用类");
        if (Boolean.TRUE.equals(config.get("needSwagger"))) {
            System.out.println("5. SwaggerConfig.java - Swagger配置类");
        }
        if (Boolean.TRUE.equals(config.get("needJwt"))) {
            System.out.println("6. JwtUtil.java - JWT工具类");
        }
        System.out.println("\n请在IDEA中运行时使用以下主类名:");
        System.out.println(basePackage + "." + mainClassName);
    }

    /**
     * 将字符串转换为帕斯卡命名法(PascalCase)
     */
    private String toPascalCase(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }

        StringBuilder result = new StringBuilder();
        boolean capitalizeNext = true;

        for (char ch : str.toCharArray()) {
            if (Character.isLetterOrDigit(ch)) {
                if (capitalizeNext) {
                    result.append(Character.toUpperCase(ch));
                    capitalizeNext = false;
                } else {
                    result.append(ch);
                }
            } else {
                capitalizeNext = true;
            }
        }

        return result.toString();
    }

    /**
     * 处理模板文件
     * @param templateName 模板文件名
     * @param outputPath 输出文件路径
     * @param data 模板数据
     */
    private void processTemplate(String templateName, String outputPath, Map<String, Object> data) throws Exception {
        // 配置FreeMarker
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
        cfg.setClassLoaderForTemplateLoading(getClass().getClassLoader(), "templates/spring-boot");
        cfg.setDefaultEncoding("UTF-8");

        // 确保输出目录存在
        File outputFile = new File(outputPath);
        outputFile.getParentFile().mkdirs();

        // 处理模板
        Template template = cfg.getTemplate(templateName);
        try (Writer writer = new FileWriter(outputFile)) {
            template.process(data, writer);
        }
    }

    /**
     * 创建项目目录结构
     * @param baseDir 基础目录
     * @param basePackage 基础包名
     */
    private void createDirectoryStructure(String baseDir, String basePackage) throws IOException {
        // 创建标准的Maven项目结构
        List<String> directories = Arrays.asList(
            "src/main/java/" + basePackage.replace(".", "/"),
            "src/main/resources",
            "src/main/resources/templates",
            "src/main/resources/static",
            "src/main/resources/mapper",
            "src/main/resources/mybatis",
            "src/test/java/" + basePackage.replace(".", "/"),
            "src/test/resources"
        );

        // 创建基础包下的标准目录结构
        List<String> packageDirs = Arrays.asList(
            "controller",
            "service",
            "service/impl",
            "mapper",
            "entity",
            "config",
            "util",
            "common",
            "common/exception",
            "common/result"
        );

        // 创建所有目录
        for (String dir : directories) {
            Files.createDirectories(Paths.get(baseDir, dir));
        }

        // 创建包目录
        String basePath = Paths.get(baseDir, "src/main/java", basePackage.replace(".", "/")).toString();
        for (String dir : packageDirs) {
            Files.createDirectories(Paths.get(basePath, dir));
        }
    }
}
